using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace ProjectNocturnalFool
{
    public enum ScreenLoad
    {
        Title,
        Arena,
        Options,
        AdventureSelect,
        PartyCreation,
        CharacterCreation,

        GenderEdit,
        RaceEdit,
        ClassEdit,
        AlignmentEdit,
        AbilitiesEdit

    }


    /// <summary>
    /// The screen manager is a component which manages one or more GameScreen
    /// instances. It maintains a stack of screens, calls their Update and Draw
    /// methods at the appropriate times, and automatically routes input to the
    /// topmost active screen.
    /// </summary>
    public sealed class ScreenMgr
    {
        #region Fields

        List<UserControl> userControls = new List<UserControl>();

        SpriteFont font;
        Texture2D blankTexture;

        Dictionary<ScreenLoad, string> screenLoadDictionary = new Dictionary<ScreenLoad,string>();
        Dictionary<Button_Type, ScreenLoad> buttonLoadDictionary = new Dictionary<Button_Type, ScreenLoad>();

        List<Tuple<string, int, int>> updateList = new List<Tuple<string, int, int>>();

        UserControl HeldControl;
        UserControl SelectedControl;
                
        #endregion
                
        #region Initialization

        /// <summary>
        /// Allocate ourselves.
        /// We have a private constructor, so no one else can.
        /// </summary>
        static readonly ScreenMgr _instance = new ScreenMgr();

        /// <summary>
        /// Access SiteStructure.Instance to get the singleton object.
        /// Then call methods on that instance.
        /// </summary>
        public static ScreenMgr Instance
        {
            get { return _instance; }
        }


        /// <summary>
        /// Constructs a new screen manager component.
        /// </summary>
        public ScreenMgr()
        {

        }


        /// <summary>
        /// Initializes the screen manager component.
        /// </summary>
        public void Initialize()
        {
            
        }


        /// <summary>
        /// Load your graphics content.
        /// </summary>
        public void LoadContent()
        {            
            // Load content belonging to the screen manager.
            ContentManager content = TacticsGame.Instance.Content;

            font = TacticsGame.Instance.Content.Load<SpriteFont>("Fonts/menufont");
            blankTexture = TacticsGame.Instance.Content.Load<Texture2D>("Misc/blank");

            CreateLoadDicationary();

            // Tell each of the screens to load their content.
            foreach (UserControl ctrl in userControls)
            {
                ctrl.LoadContent();            
            }

            //textControl = UILoader.addTextMessenger();

            //userControls.Add(textControl);

        }


        /// <summary>
        /// Unload your graphics content.
        /// </summary>
        public  void UnloadContent()
        {
            // Tell each of the screens to unload their content.
            foreach (UserControl ctrl in userControls)
            {
                ctrl.UnloadContent();
            }
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Allows each screen to run logic.
        /// </summary>
        public void Update(GameTime gameTime)
        {
            updateControls(gameTime);
        }

        /// <summary>
        /// Tells each screen to draw itself.
        /// </summary>
        public  void Draw(GameTime gameTime)
        {
            //textControl.hidden = true;
            VirtualScreen.Instance.BeginCapture();

            TacticsGame.Instance.GraphicsDevice.Clear(Color.CornflowerBlue);
            foreach (UserControl ctrl in userControls)
            {
                if (ctrl.hidden)
                    continue;

                ctrl.Draw(gameTime);
            }

            DebugMgr.Instance.Draw();

            VirtualScreen.Instance.EndCapture();

            TacticsGame.Instance.GraphicsDevice.Clear(Color.Black);
            TacticsGame.Instance.spriteBatch.Begin();
            VirtualScreen.Instance.Draw();
            TacticsGame.Instance.spriteBatch.End();

        }

       
        #endregion

        #region Private Helper Methods

        private void updateControls(GameTime gameTime)
        {
            bool controlCollisionFound;

            UserControl ctrl;

            if (!InputMgr.Instance.isMouseHeld(Click.Left))
            {
                HeldControl = null;
            }

            controlCollisionFound = HeldControl != null;
            for (int i = userControls.Count - 1; i > -1; i--)
            {
                ctrl = userControls[i];

                if (ctrl.hidden)
                    continue;

                int x, y;
                InputMgr.Instance.getMouse(out x, out y);


                if (HeldControl != ctrl)
                {
                    ctrl.Hover = false;
                    ctrl.Held = false;
                }

                if (!controlCollisionFound)
                {
                    if ((x >= ctrl.x) && (x < ctrl.x + ctrl.width)
                        && (y >= ctrl.y) && (y < ctrl.y + ctrl.height))
                    {
                        ctrl.Hover = true;
                        controlCollisionFound = true;

                        if (InputMgr.Instance.isMouseClickUp(Click.Left))
                        {
                            ctrl.Selected = true;
                            ctrl.Held = false;
                            SelectedControl = ctrl;
                        }
                        else if (InputMgr.Instance.isMouseHeld(Click.Left))
                        {
                            if (SelectedControl != null)
                            {
                                SelectedControl.Selected = false;
                            }
                            ctrl.Held = true;
                            ctrl.Selected = true;
                            HeldControl = ctrl;
                        }
                    }
                }
                ctrl.Update(gameTime);
                updateList.AddRange(ctrl.updateStatus);
                ctrl.updateStatus.Clear();

            }
            HandleUpdateStatus(updateList);
            updateList.Clear();
        }



        #endregion

        #region Screen Setups

        private void HandleUpdateStatus(List<Tuple<string, int, int>> tupleList)
        {
            foreach (Tuple<string, int, int> tuple in tupleList)
            {
            if (tuple.Item1.ToString() == typeof(Button_Type).Name)
            {
                ScreenLoad screenToLoad;
                if (buttonLoadDictionary.TryGetValue((Button_Type)tuple.Item2, out screenToLoad))
                {
                    GameLogic.Instance.gameStateLogic.handleStateChange(screenToLoad);
                }
            }
            }
        }


        public void OpenScreen(ScreenLoad screen)
        {
            userControls.RemoveAll(delegate(UserControl c1) { return !c1.singleton; });
            UserScreen loadScreen;
            string namespaceString = typeof(UserScreen).Namespace;
            string ctrlName;

            if( screenLoadDictionary.TryGetValue(screen, out ctrlName))
            {
            loadScreen = (UserScreen)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(namespaceString + "." + ctrlName);
            loadScreen.LoadContent();
            userControls.Add(loadScreen);
            loadScreen.SortControls();
            }
        }

        private void CreateLoadDicationary()
        {
            //TitleScreen
            screenLoadDictionary.Add(ScreenLoad.Title, typeof(TitleScreen).Name);
            buttonLoadDictionary.Add(Button_Type.AdventureSelectCancel, ScreenLoad.Title);
            buttonLoadDictionary.Add(Button_Type.ArenaToTitle, ScreenLoad.Title);

            //BoardGame
            screenLoadDictionary.Add(ScreenLoad.Arena, typeof(GameBoardScreen).Name);
            buttonLoadDictionary.Add(Button_Type.TitleArenaStart, ScreenLoad.Arena);
            buttonLoadDictionary.Add(Button_Type.PartySelectBegin, ScreenLoad.Arena);

            //Character Edit
            screenLoadDictionary.Add(ScreenLoad.CharacterCreation, typeof(CharacterEditScreen).Name);
            buttonLoadDictionary.Add(Button_Type.PortraitEdit, ScreenLoad.CharacterCreation);
            buttonLoadDictionary.Add(Button_Type.GenderButton, ScreenLoad.CharacterCreation);
            buttonLoadDictionary.Add(Button_Type.GenderCancel, ScreenLoad.CharacterCreation);

            //Gender Edit
            screenLoadDictionary.Add(ScreenLoad.GenderEdit, typeof(GenderScreen).Name);
            buttonLoadDictionary.Add(Button_Type.EditGender, ScreenLoad.GenderEdit);
            
            //Adventure Select
            screenLoadDictionary.Add(ScreenLoad.AdventureSelect, typeof(AdventureSelectScreen).Name);
            buttonLoadDictionary.Add(Button_Type.TitleCampaignNew, ScreenLoad.AdventureSelect);
            buttonLoadDictionary.Add(Button_Type.PartySelectCancel, ScreenLoad.AdventureSelect);
            
            //Party Select
            screenLoadDictionary.Add(ScreenLoad.PartyCreation, typeof(PartySelectScreen).Name);
            buttonLoadDictionary.Add(Button_Type.AdventureSelectRegular, ScreenLoad.PartyCreation);
            buttonLoadDictionary.Add(Button_Type.EditBack, ScreenLoad.PartyCreation);
            buttonLoadDictionary.Add(Button_Type.EditConfirm, ScreenLoad.PartyCreation);

            



        }


        #endregion
    }
}
